home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / Pascal / OneTest / OneEvents.p < prev    next >
Text File  |  1994-10-29  |  7KB  |  228 lines

  1. {YET ANOTHER WAY TO ISOLATE SOME REPETITIVE CODE FROM YOUR ORIGINAL CODE}
  2. {}
  3. {Minimal event loop handling for a program with usually only one window, and one About… selection.}
  4. {The full demo is a very simple skeleton program that is easy to build new programs from.}
  5. {}
  6. {For bigger projects, TransSkel is a lot better, but for VERY small hacks, this saves quite a few kilobytes.}
  7. {(Definitely not worth it if you have some big sounds or picts!) TransSkel, though excellent, lacks a}
  8. {simple starting demo to use for quick hacks, at least one that is both as simple and as complete as}
  9. {the OneTest demo.}
  10. {}
  11. {Though I wholeheartedly recommend TransSkel in the long run, this is not only smaller, but also}
  12. {easier to understand when used as an educational example. With lots of standard code isolated to this}
  13. {file, I believe that the result is more comprehensible than any skeleton program I've seen (e.g. the}
  14. {classic Skel demo).}
  15.  
  16. {Usage:}
  17.  
  18. {You plug this unit in between the main program and your window/menu handlers, using the procedures}
  19. {listed below. The big difference between this and "Skel" is that most of the code, in this file, is reuseable}
  20. {and will seldom have to be edited, while Skel is just a demo without isolated reusable code.}
  21. {}
  22. {One idea when making the stubs was that it should be pretty easy to plug in TransSkel, once a program gets}
  23. {complicated enough to justify it.}
  24.  
  25. {Your unit StdHandlers should include the following:}
  26. {}
  27. {procedure DoUpdate(w: WindowPtr);}
  28. {procedure DoClose(w:WindowPtr);}
  29. {procedure DoAbout;}
  30. {procedure DoMenu(menuID, item: integer);}
  31. {procedure DoMouse(where: Point; mods: longint);}
  32. {procedure DoKey(theChar: char; mods: longint);}
  33. {… and you should call OneInit during startup.}
  34. {}
  35. {The flag gDone should be set to true when you want the program to quit. The global gHasCQD is}
  36. {initialized by a call to SysEnvirons during program startup, and should be used to check if Color}
  37. {QD is available.}
  38.  
  39. {Based on code from OutOfThisGWorld; it was pretty short. One of the conclusions: It is hard to get under}
  40. {2k with a program that uses windows and menus.}
  41.  
  42. unit OneEvents;
  43.  
  44. interface
  45.     uses
  46. {$ifc undefined THINK_PASCAL}
  47.         Types, QuickDraw, Events, Windows, Dialogs, Fonts, DiskInit, TextEdit, Traps, Desk, {}
  48.         Memory, SegLoad, Scrap, ToolUtils, OSEvents, OSUtils, Menus, Resources, StandardFile,{}
  49.         GestaltEqu, Files, Errors, {}
  50. {$endc}
  51.         StdHandlerStubs;
  52.  
  53.     procedure OneInit (aboutStr: Str255);
  54.     procedure PollEvents;
  55.  
  56. implementation
  57.  
  58.     const
  59.         kSleep = 0;
  60.  
  61.         appleID = 1;
  62.  
  63.     var
  64.         gWNEImplemented: Boolean;
  65.  
  66.     procedure OneInit (aboutStr: Str255);
  67.         var
  68.             appleMenu: MenuHandle;
  69.     begin
  70. {$ifc undefined THINK_PASCAL}
  71.     { Initialize all the needed managers. }
  72.         InitGraf(@qd.thePort);
  73.         InitFonts;
  74.         InitWindows;
  75.         InitMenus;
  76.         TEInit;
  77.         InitDialogs(nil);
  78.         MaxApplZone;
  79. {$endc}
  80.  
  81.         appleMenu := NewMenu(appleID, char(20)); {Apple menu symbol}
  82.         InsertMenu(appleMenu, 0);
  83.         if length(aboutStr) > 0 then
  84.             begin
  85.                 AppendMenu(appleMenu, aboutStr);
  86.                 AppendMenu(appleMenu, '(-');
  87.             end;
  88.         AddResMenu(appleMenu, 'DRVR');
  89. {Main program should call DrawMenuBar once it's done setting up its own menus.}
  90.  
  91. {Check for WNE being implemented, save in a boolean. This improves compatibility}
  92. {with (very) old system versions.}
  93.         gWNEImplemented := NGetTrapAddress($A860, ToolTrap) <> NGetTrapAddress($A89F, ToolTrap);
  94.  
  95. {Check for Color QD being available. (AA1E is GetCIcon, i.e. any CQD routine.)}
  96.         gHasCQD := NGetTrapAddress($AA1E, toolTrap) <> NGetTrapAddress($A89F, toolTrap);{_Unimplemented}
  97.  
  98.         InitCursor;
  99.     end;
  100.  
  101.     procedure HandleMenu (mSelect: LongInt);
  102.         var
  103.             menuID: Integer;
  104.             menuItem: Integer;
  105.             savePort: GrafPtr;
  106.             name: Str255;
  107.             ignore: integer;
  108.     begin
  109.         menuID := HiWord(mSelect);
  110.         menuItem := LoWord(mSelect);
  111.  
  112.         if menuID = appleID then
  113.             if menuItem = 1 then
  114.                 DoAbout
  115.             else
  116.                 begin
  117.                     GetPort(savePort);
  118.                     GetItem(GetMHandle(appleID), menuItem, name);
  119.                     ignore := OpenDeskAcc(name);
  120.                     SetPort(savePort);
  121.                 end
  122.         else if menuID <> 0 then {Zero when no menu?}
  123.             DoMenu(menuID, menuItem);
  124.         HiliteMenu(0);
  125.     end;
  126.  
  127.     procedure PollEvents;
  128.         var
  129.             anEvent: EventRecord;
  130.             theWindow: WindowPtr;
  131.             clickArea: Integer;
  132.             screenRect: Rect;
  133.             savePort: GrafPtr;
  134.             hasEvent: Boolean;
  135.  
  136.             growR: Rect;
  137.             growRes: Longint;
  138.     begin
  139.         if gWNEImplemented then
  140.             hasEvent := WaitNextEvent(everyEvent, anEvent, kSleep, nil)
  141.         else
  142.             begin
  143.                 SystemTask;    (* Handle desk accessories *)
  144.                 hasEvent := GetNextEvent(everyEvent, anEvent);
  145.             end;
  146.  
  147.         if hasEvent then
  148.             case anEvent.what of
  149.                 mouseDown: 
  150.                     begin
  151.                         clickArea := FindWindow(anEvent.where, theWindow);
  152.  
  153.                         if clickArea = inDrag then
  154.                             begin
  155.                                 screenRect := GetGrayRgn^^.rgnBBox;
  156.                                 DragWindow(theWindow, anEvent.where, screenRect);
  157.                             end
  158.                         else if clickArea = inGoAway then
  159.                             begin
  160.                                 if TrackGoAway(theWindow, anEvent.where) then
  161.                                     DoClose(theWindow);
  162.                             end
  163.  
  164.                         else if clickArea = inMenuBar then
  165.                             begin
  166.                                 HandleMenu(MenuSelect(anEvent.where));
  167.                             end
  168.                         else if clickArea = inContent then
  169.                             begin
  170.                                 if theWindow <> FrontWindow then
  171.                                     SelectWindow(theWindow)
  172.                                 else
  173.                                     DoMouse(anEvent.where, anEvent.modifiers);
  174.                             end
  175.                         else if clickArea = inGrow then
  176.                             begin
  177.                                 growR := GetGrayRgn^^.rgnBBox;
  178.                                 InsetRect(growR, 10, 10); {Wrong rect???}
  179.                                 growRes := GrowWindow(theWindow, anEvent.where, growR);
  180.                                 if growRes <> 0 then
  181.                                     begin
  182.                                         SizeWindow(theWindow, LoWord(growRes), HiWord(growRes), false);
  183.                                         GetPort(savePort);
  184.                                         SetPort(theWindow);
  185.                                         InvalRect(theWindow^.portRect);
  186.                                         SetPort(savePort);
  187.                                     end;
  188.                             end;
  189.  
  190.                     end; {mouseDown}
  191.                 updateEvt: 
  192.                     begin
  193.                         theWindow := WindowPtr(anEvent.message);
  194.  
  195.                         GetPort(savePort);
  196.                         SetPort(theWindow);
  197.                         BeginUpdate(theWindow);
  198.                         DoUpdate(theWindow);
  199.                         EndUpdate(theWindow);
  200.                         SetPort(savePort);
  201.                     end; {updateEvt}
  202.                 keyDown, autoKey: 
  203.                     begin
  204.                         if BitAnd(anEvent.modifiers, cmdKey) <> 0 then
  205.                             HandleMenu(MenuKey(Char(BitAnd(anEvent.message, charCodeMask))))
  206.                         else
  207.                             DoKey(Char(BitAnd(anEvent.message, charCodeMask)), anEvent.modifiers);
  208.                     end; {key}
  209. {activateEvt: }
  210. {begin}
  211. {What's appropriate here? Yet another stub, DoActivate?}
  212. {end;}
  213. {And more: suspend/resume, Apple Events… but a many simple programs can live without them.}
  214.  
  215. {Real programs must handle bad disk insertion too!}
  216.                 diskEvt:  {Handle uninitialized disks}
  217.                     if (HiWord(anEvent.message) <> noErr) then
  218.                         begin
  219.                             DILoad;
  220.                             if DIBadMount(Point($00800080), anEvent.message) <> noErr then
  221.                                 ;
  222.                             DIUnload;
  223.                         end;{diskEvt, if}
  224.                 otherwise
  225.             end; {case}
  226.     end; {PollEvent}
  227.  
  228. end.